/******************************************************************************* 
 * Copyright (C) 2012-2015 Microfountain Technology, Inc. All Rights Reserved. 
 * 
 * Unauthorized copying of this file, via any medium is strictly prohibited.   
 * Proprietary and confidential
 * 
 * Last Modified: 2015-9-17 19:33:20
 ******************************************************************************/
package cn.com.xy.sms.sdk.db;

import java.io.BufferedReader;
import java.io.File;
import java.util.Hashtable;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import cn.com.xy.sms.sdk.constant.Constant;
import cn.com.xy.sms.sdk.db.entity.ContactsManager;
import cn.com.xy.sms.sdk.db.entity.NumberInfoManager;
import cn.com.xy.sms.sdk.log.LogManager;
import cn.com.xy.sms.sdk.util.FileUtils;

/* SDK-428 huangzhiqiang 20160530 start */
public class ContactsDBManager {

    public static Object dblock = new Object();
    public static final String DATA_BASE_NAME = "duoqu_contacts.db";
    
    /*IMOO-20 zhaojiangwei 20161221 start */
    private static final int dataBaseVersion = 6;
    /*IMOO-20 zhaojiangwei 20161221 end */
    
    private static MyDbHelper dbHelper = null;
    private static int timeOut = 1000;
    private static int sleepTime = 100;
    private static Hashtable<SQLiteDatabase, Integer> listDB = new Hashtable<SQLiteDatabase, Integer>();

    private static SQLiteDatabase createSQLiteDatabase(Context contexts) {

        synchronized (listDB) {
            if (listDB.size() >= 10) {
                return null;
            }
            if (contexts == null) {
                LogManager.w(Constant.TAG, "ContactsDBManager createSQLiteDatabase: contexts is null");
                return null;
            }
            MyDbHelper helper = getHelper(contexts);
            SQLiteDatabase db = helper.getReadableDatabase();
            Integer cnt = null;
            if (db != null) {
                cnt = listDB.get(db);
                if (cnt == null) {
                    cnt = 1;
                } else {
                    cnt++;
                }
                listDB.put(db, cnt);
                if (!db.isOpen()) {
                    listDB.remove(db);
                    return null;
                }
            }
            return db;
        }
    }

    public static void close(SQLiteDatabase db) {
        try {
            if (db == null) {
                LogManager.d(Constant.TAG, "ContactsDBManager ^^^^^^^^ db close db is null");
                return;
            }
            synchronized (listDB) {
                if (!db.isOpen()) {
                    listDB.remove(db);
                    LogManager.d(Constant.TAG, "ContactsDBManager $$$$$ db close is not open");
                } else {
                    Integer cnt = listDB.get(db);

                    if (cnt == null) {
                        LogManager.d(Constant.TAG, "ContactsDBManager $$$$$ db close cnt is null ");
                        // 这种情况如果发生就是有问题的
                        // db.close();
                    } else {
                        cnt = cnt - 1;
                        if (cnt == 0) {
                            listDB.remove(db);
                            db.close();
                        } else {
                            listDB.put(db, cnt);
                        }
                    }
                }
            }
            // if (listDB.size() == 0) {
            // if (dbHelper != null) {
            // // dbHelper.close();
            // }
            // }
        } catch (Throwable e) {
            LogManager.e(Constant.TAG, "ContactsDBManager close error: ");
        }

    }

    public static SQLiteDatabase getSQLiteDatabase() {

        SQLiteDatabase sb = null;
        long start = System.currentTimeMillis();
        long end = 0;
        while (sb == null) {

            sb = createSQLiteDatabase(Constant.getContext());
            if (sb != null) {
                if (sb.inTransaction()) {
                    LogManager.d(Constant.TAG,"ContactsDBManager getSQLiteDatabase inTransaction hashcode: ");
                }
                return sb;
            }
            end = System.currentTimeMillis();
            end = (end - start);
            if (end >= timeOut) {
                break;
            }
            try {
                Thread.sleep(sleepTime);

            } catch (InterruptedException e) {
                /*SDK-550 hewengao 20160719 start*/
                LogManager.w(Constant.TAG, "getSQLiteDatabase error: ", e);
                /*SDK-550 hewengao 20160719 end*/
            }
        }
        return sb;
    }

    private synchronized static MyDbHelper getHelper(Context contexts) {
        if (dbHelper == null) {
            dbHelper = new MyDbHelper(contexts, DATA_BASE_NAME, null, dataBaseVersion);
        }
        return dbHelper;
    }

    private static class MyDbHelper extends SQLiteOpenHelper {
        public MyDbHelper(Context contexts, String name, CursorFactory factory, int version) {
            super(contexts, name, factory, version);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            try {
                createDb(db);
                createIndex(db);
            } catch (Throwable e) {
                /*SDK-550 hewengao 20160719 start*/
                LogManager.e(Constant.TAG, "ContactsDBManager MyDbHelper onCreate error: ", e);
                /*SDK-550 hewengao 20160719 end*/
            }
        }

        @Override
        public void onOpen(SQLiteDatabase db) {
            try {
                super.onOpen(db);
            } catch (Throwable e) {
                /*SDK-550 hewengao 20160719 start*/
                LogManager.w(Constant.TAG, "ContactsDBManager MyDbHelper onOpen error: ", e);
                /*SDK-550 hewengao 20160719 end*/
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            createDb(db);
            createIndex(db);
            
            /*IMOO-200 zhaojiangwei 20161221 start */
            addColumn(db, NumberInfoManager.ADD_COLUMN_T9FLAG);
            /*IMOO-200 zhaojiangwei 20161221 end */
        }

        @Override
        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            try {
                db.execSQL(NumberInfoManager.DROP_TABLE);
            } catch (Throwable e) {
                /*SDK-550 hewengao 20160719 start*/
                LogManager.w(Constant.TAG, "ContactsDBManager onDowngrade", e);
                /*SDK-550 hewengao 20160719 end*/
            }
            createDb(db);
        }
    }

    private static void addColumn(SQLiteDatabase sqLiteDatabase, String sql) {
        try {
            sqLiteDatabase.execSQL(sql);
        } catch (Throwable e) {
        }
    }
    
    public static void createDb(SQLiteDatabase SQLiteDatabase) {
        try {
            SQLiteDatabase.execSQL(ContactsManager.CREATE_CONTACTS_SQL);
            SQLiteDatabase.execSQL(NumberInfoManager.CREATE_TABLE);
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "ContactsDBManager createDb error:", e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }

    public static void createIndex(SQLiteDatabase SQLiteDatabase) {
        try {
            SQLiteDatabase.execSQL(NumberInfoManager.CREATE_INDEX_LAST_QUERY_TIME);
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "ContactsDBManager createIndex error:", e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }

    private static SQLiteDatabase getReadSQLiteDatabase() {
        return getSQLiteDatabase();
    }

    public static XyCursor query(String tableName, String[] columns, String selection, String[] selectionArgs)
            throws Exception {
        return query(false, tableName, columns, selection, selectionArgs, null, null, null, null);
    }

    private static boolean dbInTransaction(SQLiteDatabase mySQLiteDatabase) {
        if (mySQLiteDatabase != null && mySQLiteDatabase.inTransaction()) {
            close(mySQLiteDatabase);
            LogManager.d(Constant.TAG, "ContactsDBManager db inTransaction threadName:"
                    ,Thread.currentThread().getName());
            return true;
        }
        return false;
    }

    public static XyCursor query(boolean distinct, String tableName, String[] columns, String selection,
            String[] selectionArgs, String groupBy, String having, String orderBy, String limit) throws Exception {
        XyCursor xyCursor = null;
        SQLiteDatabase mySQLiteDatabase = null;
        try {
            mySQLiteDatabase = getReadSQLiteDatabase();
            if (mySQLiteDatabase == null) {
                return null;
            }
            if (dbInTransaction(mySQLiteDatabase)) {
                return null;
            }
            Cursor cursor = mySQLiteDatabase.query(distinct, tableName, columns, selection, selectionArgs, groupBy,
                    having, orderBy, limit);
            /* SDK-531 huangzhiqiang 20160711 start */
            xyCursor = new XyCursor(mySQLiteDatabase, cursor, 2);
            /* SDK-531 huangzhiqiang 20160711 end */
        } catch (Throwable e) {
            close(mySQLiteDatabase);
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "ContactsDBManager  1query error: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
        return xyCursor;
    }

    public static XyCursor query(String tableName, String[] columns, String selection, String[] selectionArgs,
            String groupBy, String having, String orderBy, String limit) throws Exception {
        // initDbManager();
        XyCursor xyCursor = null;
        SQLiteDatabase mySQLiteDatabase = null;
        try {
            mySQLiteDatabase = getSQLiteDatabase();
            if (dbInTransaction(mySQLiteDatabase)) {
                return null;
            }
            Cursor cursor = mySQLiteDatabase.query(tableName, columns, selection, selectionArgs, groupBy, having,
                    orderBy, limit);
            /* SDK-531 huangzhiqiang 20160711 start */
            xyCursor = new XyCursor(mySQLiteDatabase, cursor, 2);
            /* SDK-531 huangzhiqiang 20160711 end */
        } catch (Throwable e) {
            close(mySQLiteDatabase);
            /*SDK-550 hewengao 20160719 start*/
            LogManager.e(Constant.TAG, "ContactsDBManager 2query error: ", e);
            /*SDK-550 hewengao 20160719 end*/
        } finally {

        }
        return xyCursor;
    }

    public static int delete(String tableName, String whereClause, String[] whereArgs) throws Exception {
        // initDbManager();

        synchronized (dblock) {
            int res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase();
                res = mySQLiteDatabase.delete(tableName, whereClause, whereArgs);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static int update(String tableName, ContentValues values, String whereClause, String[] whereArgs)
            throws Exception {
        synchronized (dblock) {
            int res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase();
                res = mySQLiteDatabase.update(tableName, values, whereClause, whereArgs);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static long insert(String tableName, ContentValues values) throws Exception {
        synchronized (dblock) {
            long res = -1;
            SQLiteDatabase mySQLiteDatabase = null;
            try {
                mySQLiteDatabase = getSQLiteDatabase();
                res = mySQLiteDatabase.insert(tableName, null, values);
            } catch (Throwable e) {
                res = -1;
            } finally {
                close(mySQLiteDatabase);
            }
            return res;
        }
    }

    public static void closeDB(String filePath, boolean isDeleteFile, java.io.LineNumberReader r, BufferedReader bw,
            SQLiteDatabase db) {
        File file = null;
        try {
            if (isDeleteFile) {
                file = new File(filePath);
            }
        } catch (Throwable ex) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "ContactsDBManager closeDB error: " , ex);
            /*SDK-550 hewengao 20160719 end*/
        }
        closeDB(file, isDeleteFile, r, bw, db);
    }

    public static void closeDB(File file, boolean isDeleteFile, java.io.LineNumberReader r, BufferedReader bw,
            SQLiteDatabase db) {
        try {
            try {
                if (isDeleteFile) {
                    FileUtils.deleteAllFile(file);
                }
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            try {
                if (r != null)
                    r.close();
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            try {
                if (bw != null)
                    bw.close();
            } catch (Throwable e2) {
                // TODO: handle Throwable
            }

            if (db != null) {
                try {
                    if (db.inTransaction()) {
                        db.setTransactionSuccessful();
                        db.endTransaction();
                    }
                } catch (Throwable e) {
                    // e.printStackTrace();
                    /*SDK-550 hewengao 20160719 start*/
                    LogManager.w(Constant.TAG, "ContactsDBManager closeDB: ", e);
                    /*SDK-550 hewengao 20160719 end*/
                } finally {
                    ContactsDBManager.close(db);
                }
            }
        } catch (Throwable e) {
            /*SDK-550 hewengao 20160719 start*/
            LogManager.w(Constant.TAG, "ContactsDBManager closeDB error: ", e);
            /*SDK-550 hewengao 20160719 end*/
        }
    }
}
/* SDK-428 huangzhiqiang 20160530 end */
